<?php
/*
  +----------------------------------------------------------------------+
  | UCLibKVDB.php                                                                           |
  +----------------------------------------------------------------------+
  | Copyright (c) 2010 snda.com - Web Development Center            |
  +----------------------------------------------------------------------+
  | Key-Value 数据库操作类                                                               |
  |  目前采用Tokyo Cabinet，采用Memcache库进行操作                     |
  +----------------------------------------------------------------------+
  | Authors: Xu Pengcheng <xupengcheng@snda.com>                     |
  +----------------------------------------------------------------------+
*/

require_once(dirname(__FILE__).'/UCLibLogger.php');

class UCLibKVDB {
	public static $CHANNEL_STATISTICS = "stat";
	public static $CHANNEL_TICKETID_SDOACCOUNT = "ticketid_sdoaccount";
	public static $CHANNEL_SDOACCOUNT_TICKETID = "sdoaccount_ticketid";
	public static $CHANNEL_SDOACCOUNT_EXTERNACCOUNT = "sdoaccount_externaccount";
	public static $CHANNEL_EXTERNACCOUNT_SDOACCOUNT = "externaccount_sdoaccount";
	public static $CHANNEL_SHORT_LONG = "short_long";
	public static $CHANNEL_LONG_SHORT = "long_short";
	public static $CHANNEL_SHORT_COUNTER = "short_counter";
	public static $CHANNEL_ACTIVE_CODE = "active_code";

	protected $_channel_name;
	protected $_conn = null;
	protected $_auto_close = true;
	
    private $_host = '';
    private $_port = '';
	/**
	 * 构造函数
	 * @param const_server: 指定的模块名
	 *        可选值：UCLibKVDB::$CHANNEL_STATISTICS
	 * @param auto_close: 每次操作是否自动关闭连接，默认为true
	 *        如果设置为false,请在操作完成之后调用close函数关闭
	 */
	function __construct($channel_name, $auto_close = true) {
		$this->_channel_name = $channel_name;
		$this->_auto_close = $auto_close;
	}
	
	function __destruct(){
		$this->close();
	}
	
    function _real_connect($host, $port, $timeout=0.5) {
        $this->_host = $host;
        $this->_port = $port;
        
        $_time_start = microtime(true);
        $conn = $this->_conn->connect($host, $port, $timeout);    
        if( !$conn ) {
             UCLibLogger::rpc("Connect Error:".$this->_channel_name, microtime(true) - $_time_start, $host, $port, UCLIB_LOG_RPC_TYPE_TT);
        }
        return $conn;
    }
	/**************连接DB服务器**************/
	protected function _connect() {
		if ($this->_conn) return $this->_conn;
		$this->_conn = new Memcache;
		switch($this->_channel_name) {
			case self::$CHANNEL_STATISTICS:
				if (defined('__UC_ENV') && __UC_ENV == 'DEV') {
					$this->_real_connect("10.129.128.15", 11211);
				} else if (defined('__UC_ENV') && __UC_ENV == 'TEST') {
					$this->_real_connect("10.10.85.4", 11211);
				} else {
					$this->_real_connect("10.150.20.12", 11218);
				}
				return $this->_conn;
			case self::$CHANNEL_TICKETID_SDOACCOUNT:
				if (defined('__UC_ENV') && __UC_ENV == 'DEV') {
					$this->_real_connect("10.129.128.15", 11212);
				} else if (defined('__UC_ENV') && __UC_ENV == 'TEST') {
					$this->_real_connect("10.10.85.4", 11211);
				} else {
					$this->_real_connect("10.150.20.12", 11218);
				}
				return $this->_conn;
			case self::$CHANNEL_SDOACCOUNT_TICKETID:
				if (defined('__UC_ENV') && __UC_ENV == 'DEV') {
					$this->_real_connect("10.129.128.15", 11213);
				} else if (defined('__UC_ENV') && __UC_ENV == 'TEST') {
					$this->_real_connect("10.10.85.4", 11211);
				} else {
					$this->_real_connect("10.150.20.12", 11218);
				}
				return $this->_conn;
			case self::$CHANNEL_SDOACCOUNT_EXTERNACCOUNT:
				if (defined('__UC_ENV') && __UC_ENV == 'DEV') {
					$this->_real_connect("10.129.128.15", 11214);
				} else if (defined('__UC_ENV') && __UC_ENV == 'TEST') {
					$this->_real_connect("10.10.85.4", 11211);
				} else {
					$this->_real_connect("10.150.20.12", 11218);
				}
				return $this->_conn;
			case self::$CHANNEL_EXTERNACCOUNT_SDOACCOUNT:
				if (defined('__UC_ENV') && __UC_ENV == 'DEV') {
					$this->_real_connect("10.129.128.15", 11215);
				} else if (defined('__UC_ENV') && __UC_ENV == 'TEST') {
					$this->_real_connect("10.10.85.4", 11211);
				} else {
					$this->_real_connect("10.150.20.12", 11218);
				}
				return $this->_conn;
			case self::$CHANNEL_SHORT_LONG:
				if (defined('__UC_ENV') && __UC_ENV == 'DEV') {
					$this->_real_connect("10.129.128.15", 11216);
				} else if (defined('__UC_ENV') && __UC_ENV == 'TEST') {
					$this->_real_connect("10.10.85.4", 11211);
				} else {
					$this->_real_connect("10.150.20.12", 11218);
				}
				return $this->_conn;
			case self::$CHANNEL_LONG_SHORT:
				if (defined('__UC_ENV') && __UC_ENV == 'DEV') {
					$this->_real_connect("10.129.128.15", 11217);
				} else if (defined('__UC_ENV') && __UC_ENV == 'TEST') {
					$this->_real_connect("10.10.85.4", 11211);
				} else {
					$this->_real_connect("10.150.20.12", 11218);
				}
				return $this->_conn;
			case self::$CHANNEL_SHORT_COUNTER:
				if (defined('__UC_ENV') && __UC_ENV == 'DEV') {
					$this->_real_connect("10.129.128.15", 11218);
				} else if (defined('__UC_ENV') && __UC_ENV == 'TEST') {
					$this->_real_connect("10.10.85.4", 11211);
				} else {
					$this->_real_connect("10.150.20.12", 11218);
				}
				return $this->_conn;
			case self::$CHANNEL_ACTIVE_CODE:
				if (defined('__UC_ENV') && __UC_ENV == 'DEV') {
					$this->_real_connect("10.129.128.15", 11219);
				} else if (defined('__UC_ENV') && __UC_ENV == 'TEST') {
					$this->_real_connect("10.10.85.4", 11211);
				} else {
					$this->_real_connect("10.150.20.12", 11218);
				}
				return $this->_conn;
		}
		trigger_error("bad channel name: ".$this->_channel_name, E_USER_ERROR);
	}

	/************断开DB服务器*****************/
	public function close() {
		if ($this->_conn) {
			@$this->_conn->close();
			$this->_conn = null;
		}
	}
	
	/******************读取DB中的数据**************/
	public function get($key){
		if(!$key){
			return false;
		}
		$_time_start = microtime(true);
		$this->_connect();
		if (!$this->_conn) return false;

		$result = null;
		//批量读取
		if(is_array($key)){
			$result = array();
			foreach ($key as $k){
				$result[] = $this->_conn->get($k);
			}
		} else {
			//读取单个KEY记录
			$result =  $this->_conn->get($key);
		}
		if ($this->_auto_close) $this->close();
		UCLibLogger::rpc("read:".$this->_channel_name.'_'.$key, microtime(true) - $_time_start, $this->_host, $this->_port, UCLIB_LOG_RPC_TYPE_TT);
		return $result;
	}
	
	/**************往DB中写入数据****************/
	public function put($key, $val){
		if(!$key) return false;
		$_time_start = microtime(true);
		$this->_connect();
		if (!$this->_conn) return false;
		$ret = $this->_conn->set($key, $val);
		if ($this->_auto_close) $this->close();
		UCLibLogger::rpc("write:".$this->_channel_name.'_'.$key, microtime(true) - $_time_start, $this->_host, $this->_port, UCLIB_LOG_RPC_TYPE_TT);
		return $ret;
	}
	
	/**************往DB中增加数据值****************/
	public function increment($key, $val){
		if(!$key) return false;
		$_time_start = microtime(true);
		$this->_connect();
		if (!$this->_conn) return false;
		$ret = $this->_conn->increment ($key, $val);
		if ($ret === false) {
			$ret = $this->_conn->set($key, $val > 0 ? $val : 0);
		}
		if ($this->_auto_close) $this->close();
		UCLibLogger::rpc("write:".$this->_channel_name.'_'.$key, microtime(true) - $_time_start, $this->_host, $this->_port, UCLIB_LOG_RPC_TYPE_TT);
		return $ret;
	}
	
	/******************从DB中删除数据*****************/
	public function delete($key){
		if(!$key) return false;
		$_time_start = microtime(true);
		$this->_connect();
		if (!$this->_conn) return false;
		//批量删除
		if(is_array($key)){
			foreach ($key as $k){
				$this->_conn->delete($k);
			}
		} else {
			$this->_conn->delete($key);
		}
		if ($this->_auto_close) $this->close();
		UCLibLogger::rpc("delete:".$this->_channel_name.'_'.$key, microtime(true) - $_time_start, $this->_host, $this->_port, UCLIB_LOG_RPC_TYPE_TT);
	}
}

/*$db = new KVDB(KVDB::$CHANNEL_STATISTICS);
$db->put("test1", "value1");
echo $db->get("test1");
$db->delete("test1");
echo $db->get("test1"); */
?>